1. /* sdfdsdiv.cpp by K.Tsuru */
  2. // function ID = 325 DRADIX only
  3. /*********************************************************************
  4. SDouble class
  5. It divides 'm' by a small integer 'n'.
  6. m/n 0 < n < ULONG_MAX/radix
  7. Pay attention to the case in which the result is a recurring decimal.
  8. *********************************************************************/
  9. #ifndef SN_H
  10. #include "sn.h"
  11. #endif
  12. static const char* func = "DsDiv"; // add "const" since version 2.192
  13. /*****************************************************************
  14. sub-function
  15. It checks that "1/x" is a recurring decimal or not in radix DRADIX.
  16. ******************************************************************/
  17. static int IsCyclic(ulong x){
  18. if(x == 0) return 0;
  19. while((x % 2uL) == 0) x /= 2uL;
  20. if(x == 1uL) return 0; // x = 2^p
  21. while((x % 5uL) == 0) x /= 5uL;
  22. return x != 1uL;
  23. }
  24. SDouble DsDiv(const SDouble& m, ulong n){
  25. ulong rdx = (ulong)m.Radix();
  26. const uint minFig = 7u; //It reserves 7 figures(size is 8) at least.
  27. if(rdx != DRADIX) m.SetError(m.RADIX_ERR, "Use XsDiv", 325);
  28. if( n > m.SlOpMaxValue() ) m.SetError(m.OUT_OF_RANGE, func, 325);
  29. if( (n == 1uL) || (m.Sign(325) == 0) ) return m;
  30. if(n == 0) m.SetError(m.DIVIDED_BY_ZERO, func, 325);
  31. uint cur_max_sz = m.CurrentMaxSize(), rsz;
  32. SDouble result;
  33. ulong w, r;
  34. int i, j, top, end, rf, shift = 0;
  35. //"result" is a long decimal?
  36. int rIsLong = (m.Last() >= cur_max_sz) ? 1 : IsCyclic(n);
  37. //The series function calls this one many times in the fixed point mode.
  38. //It separately treats the floating point and fixed point modes to gain speed.
  39. fType* rv;
  40. if(!m.IsPointFixed()){ //floating point mode
  41. const fType* mv;
  42. result.rdxExp = m.rdxExp;
  43. mv = m.ReadFigures();
  44. top = 1;
  45. end = (int)min(m.Last(), cur_max_sz-1u);//The Pi() has figures more than "cur_max_sz".
  46. rsz = rIsLong ? cur_max_sz : max((uint)end+1u, minFig);
  47. result.valloc(rsz, 0);
  48. rv = result.figure.Elements();
  49. w = mv[1]/n; //It checks whether the first figure of quotient is zero ot not.
  50. if(w == 0){ //first figure is zero
  51. rf = 1; shift = 1; r = mv[1];
  52. w = r*rdx+mv[2];//first two figures
  53. if( w < n){ //second figure is also zero
  54. shift++; r = w; //It takes first two figures as remainder 'r'.
  55. }
  56. result.rdxExp -= shift; //to set upper position by 'shift'
  57. } else {
  58. rv[1] = (fType)w; //set the first decimal place
  59. r = mv[1]%n; rf = 2;
  60. }
  61. end -= shift; // i+shift <= end+shift <= m.Last(), end < cur_max_sz
  62. if(end <= 0){ //It may occure when it devides one figure by 'n'.
  63. end = 0; i = 1; top = 0;
  64. } else {
  65. #ifndef NDEBUG
  66. m.figure(end+shift); result.figure(end);
  67. #endif
  68. for(i = rf; i <= end; i++){
  69. w = rdx*r + mv[i+shift];
  70. rv[i] = fType(w/n);
  71. r = w - rv[i]*n; // r = w%n;
  72. }
  73. }
  74. } else { //fixed point mode
  75. SDouble mc;
  76. const fType* mf;
  77. int de = m.rdxExp - m.fixedExp;
  78. if(de){ //The exponent value is different from the fixed one.
  79. mc = m; //copy of m
  80. mc.Reform(325); //By moving figures it makes the same exponent.
  81. de = mc.rdxExp - m.fixedExp;
  82. if( (de > 0) && ((ulong)mc.figure(1) < n) ){
  83. //In spite of "Reform()" de > 0. mc=0.xxxx yyyy ....
  84. //The first figure of quotient is zero. 0.xxxx yyyy --> xxxx.yyyy
  85. mc.ShiftArray(-1); mc.rdxExp--;
  86. }
  87. //It maybe becomes mc=0 by "Reform()" or substitution.
  88. if(mc.Sign() == 0){ result.SetZero(); return result; }
  89. result.rdxExp = mc.rdxExp;
  90. top = (int)mc.First();
  91. end = (int)min(mc.Last(), cur_max_sz-1u);
  92. mf = mc.ReadFigures();
  93. #ifndef NDEBUG
  94. mc.figure(end);
  95. #endif
  96. } else {
  97. result.rdxExp = m.rdxExp;
  98. top = (int)m.First();
  99. end = (int)min(m.Last(), cur_max_sz-1u);
  100. mf = m.ReadFigures();
  101. }
  102. rsz = rIsLong ? cur_max_sz : max((uint)end+1u, minFig);
  103. result.valloc(rsz, -1);
  104. result.figure.clear(0, (uint)top);
  105. result.figure.clear((uint)end+1u);
  106. rv = result.figure.Elements();
  107. #ifndef NDEBUG
  108. result.figure(end);
  109. #endif
  110. r = 0;
  111. for( i = top; i <= end; i++){
  112. w = rdx*r + mf[i];
  113. rv[i] = fType(w/n);
  114. r = w - rv[i]*n; // r = w%n;
  115. }
  116. }
  117. #ifndef NDEBUG
  118. assert(end >= top);
  119. #endif
  120. /******** processing common to floating and fixed point modes **********/
  121. //processing for non-zero remainder
  122. if(r && !rIsLong){ //Meybe the result is a finite decimal fraction.
  123. int z = (int)min(result.figure.size(), cur_max_sz);
  124. z = min(z, i+4);
  125. for(; r && (i < z); i++){
  126. w = rdx*r;
  127. rv[i] = fType(w/n);
  128. r = w - rv[i]*n; // r = w%n;
  129. }
  130. end = i-1;
  131. }
  132. if(r && (end < (int)cur_max_sz)){
  133. result.valloc(cur_max_sz, 1);
  134. rv = result.figure.Elements();
  135. #ifndef NDEBUG
  136. result.figure(cur_max_sz-1);
  137. #endif
  138. for( ; i < (int)cur_max_sz; i++){
  139. //Here it is almost aliquant, then "r==0" is not checked.
  140. w = rdx*r;
  141. rv[i] = fType(w/n);
  142. r = w - rv[i]*n; // r = w%n;
  143. }
  144. end = (int)cur_max_sz-1;
  145. //In the case 2*r>=n it can raise up the precision by the rounding
  146. //but the processing becomes complicated.
  147. }
  148. #ifndef NDEBUG
  149. result.figure(end);
  150. #endif
  151. //check the figure positions
  152. j = end;
  153. rv = result.figure.Elements();
  154. while(!rv[j] && (j > top) ) j--;
  155. if( (j == top) && (result.figure(j) == 0) ){ //It becomes zero.
  156. result.rdxExp = 0;
  157. result.SetSign(0); //only in the fixed point mode, SetZero() not necessary
  158. return result;
  159. }
  160. result.aHead = (uint)j;
  161. i = top;
  162. while(!rv[i]) i++;
  163. result.aTail = i;
  164. result.SetSign( m.Sign(325) );
  165. result.Reform(325);
  166. return result;
  167. }

sdfdsdiv.cpp : last modifiled at 2017/03/13 14:31:58(5,571 bytes)
created at 2017/10/07 10:22:50
The creation time of this html file is 2017/10/07 11:29:39 (Sat Oct 07 11:29:39 2017).